package com.wl.springsecuritystudy.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

import java.text.MessageFormat;
import java.util.Optional;

/**
 * spring的工具类
 * <p>
 * spring bean 上下文<br>
 * <p>
 * 也可以通过 implements BeanFactoryPostProcessor
 * </p>
 */
@Slf4j
@Component
public class SpringUtils implements ApplicationContextAware {

    private static ApplicationContext applicationContext = null;

    @Override
    public void setApplicationContext(ApplicationContext arg0) throws BeansException {

        if (SpringUtils.applicationContext == null) {
            SpringUtils.applicationContext = arg0;
            log.debug("ApplicationContext配置完成");
        }
    }

    /**
     * 获取applicationContext
     *
     * @return
     */
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    /**
     * 通过name获取 Bean.
     *
     * @param name
     * @return
     */
    public static Optional<Object> getBean(String name) {

        if (getApplicationContext().containsBean(name)) {
            return Optional.of(getApplicationContext().getBean(name));
        }

        return Optional.empty();
    }

    /**
     * 通过class获取Bean.
     *
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> Optional<T> getBean(Class<T> clazz) {

        T obj = getApplicationContext().getBean(clazz);
        if (obj == null) {
            return Optional.empty();
        }

        return Optional.of(obj);
    }

    /**
     * 通过name,以及Clazz返回指定的Bean
     *
     * @param name
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> Optional<T> getBean(String name, Class<T> clazz) {

        T obj = getApplicationContext().getBean(name, clazz);

        if (obj == null) {
            return Optional.empty();
        }

        return Optional.of(obj);
    }

    /**
     * 如果给定的bean名字在bean定义中有别名，则返回这些别名
     *
     * @param name
     * @return
     * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
     */
    public static String[] getAliases(String name) throws NoSuchBeanDefinitionException {

        return getApplicationContext().getAliases(name);
    }

    /**
     * 获取当前上下文中的属性值
     *
     * @param key 健
     * @return
     */
    public static Optional<String> getProperty(String key) {

        if (StringUtils.isBlank(key)) {
            return Optional.empty();
        }

        Optional<Environment> envOpt = SpringUtils.getBean(Environment.class);
        if (!envOpt.isPresent()) {
            return Optional.empty();
        }

        Environment env = envOpt.get();

        return Optional.ofNullable(env.getProperty(key));
    }

    /**
     * 获取指定状态码的信息
     *
     * @param code 状态码
     * @return
     */
    public static String getStatusMessage(long code) {

        return getProperty(MessageFormat.format("notice.key.{0}", String.valueOf(code))).orElse(StringUtils.EMPTY);
    }

    /**
     * 获取通知消息
     *
     * @param key 关键字
     * @return
     */
    public static String getNoticeMessage(String key) {

        return getProperty(MessageFormat.format("notice.key.{0}", key)).orElse(StringUtils.EMPTY);
    }

}
